;ax=buf
vesa_mode dw 0
vesabuf times 512 db 0
PrintVesaInfo:
pusha
mov bp,sp
mov si,ax
lodsd
p0
p eax 
mov ax,sp
call print
mov ax,word [di + 4]
add ax,3030h
mov dx,ax
xchg al,ah
mov ah,'.'
rol eax,16
mov al,dl
mov ah,0
rol eax,16
push eax 
mov ax,sp
call print
call .nx1
db ' video-memory:',0
.nx1:
pop ax
call print
xor eax,eax
mov ax,word [di+12h]
xor bx,bx
dec bx
mul bx
rol eax,16
mov dx,ax
rol eax,16
push eax
mov cx,1
mov ax,sp
call dump_dd
pop eax
call pr_crlf
call .nx2
db 'Video-modes:',0
.nx2:
pop ax
call print
;call dump_regs
push ds ;save ds
lds ax,[es:di+0xe]
mov bx,-1
xor cx,cx
call dump_dw
;
xor bx,bx;wid
mov si,ax
lea dx,[si +2]
.bk1:
lodsw
cmp ax,-1
je .j1
push di
mov cx,ax
mov ax,4f01h
mov di,vesabuf
int 10h
test word [es:di],10000b
jnz .j2
cmp bx,word [es:di + 12h]
cmovbe bx,word [es:di + 12h]
cmovbe dx,si
.j2:
pop di
jmp .bk1
.j1:
sub dx,2
mov si,dx
lodsw
test bx,bx
cmovz ax,bx
mov [vesa_mode],ax

call pr_crlf
call .nx3
db 'Vendor:',0
.nx3:
pop ax
call print
lds ax,[es:di+0x16]
call print
call pr_space
lds ax,[es:di+0x1a]
call print
call pr_space
lds ax,[es:di+0x1e]
call print
call pr_space
pop ds
mov sp,bp
popa
ret

;read stdin
kb_read:
pushad
xor ax,ax
int 16h
popad
ret


;Print space
pr_space:
pusha
call .nx1
db ' ',0
.nx1:
pop ax
push ds
push cs
pop ds
call print
pop ds
popa
ret

pr_crlf:
pusha
call .nx1
db 13,10,0
.nx1:
pop ax
push ds
push cs
pop ds
call print
pop ds
popa
ret

;Dumps dword array
;ds:ax=off, ebx=END_dword, cx=N of words, or 0 if bx is used
dump_dd:
pusha
mov bp,cx
xor esi,esi
mov si,ax
xor eax,eax
.go:
lodsd
test cx,cx
jnz .j1
cmp eax,ebx
jz .ex
.j1:
;
push cx
mov cx,4
bswap eax
.lo:
push eax
call h2a
p0
push ax
mov ax,sp
call print
add sp,4
pop eax
shr eax,8
loop .lo
pop cx
call pr_space
;
test cx,cx
jz .go
dec bp
jnz .go
.ex:
popa
ret


;Dumps word array
;ds:ax=off, bx=END_word, cx=N of words, or 0 if bx is used
dump_dw:
pusha
mov bp,cx
mov si,ax
xor eax,eax
ddwgo:
lodsw
test cx,cx
jnz ddw1
cmp ax,bx
jz ddwex
ddw1:
;
mov dx,ax
call h2a
p0
push ax
mov al,dh
call h2a
push ax
mov ax,sp
call print
add sp,6
call pr_space
;
test cx,cx
jz ddwgo
dec bp
jnz ddwgo
ddwex:
popa
ret

;Dumps regs
dump_regs:
;8*4=32; +2
push ebp ;+4
mov ebp,esp ;esp real=ebp +6; ebp real=[ebp]
push eax
push ebx
push ecx
push edx
push esi
push edi
lea eax,[ebp + 6]
push eax ;esp
push dword [ebp] ;ebp
movzx eax,word [ebp+4]
push eax ;ret
;
xor eax,eax
mov ax,cs
p eax
mov ax,ds
p eax
mov ax,es
p eax
mov eax,ss
p eax
mov ax,fs
p eax
mov eax,gs
p eax
;
push ds
push cs
pop ds
mov bx,9 + 6
mov si,bp
dec si; hi byte of eax
call nx1
db 'EAX=',0,'EBX=',0,'ECX=',0,'EDX=',0,'ESI=',0,'EDI=',0,13,10
db 'ESP=',0,'EBP=',0,'RET=',0, 'CS= ',0, 'DS= ',0,'ES= ',0,13,10
db 'SS= ',0,'FS= ',0,'GS= ',0
nx1:
pop di
drl:
mov ax,di
call print
mov di,ax
mov cx,4
drl2:
std
xor eax,eax
lodsb
cld
call h2a
push eax
mov ax,sp
call print
pop eax
loop drl2
call nx2
db ' ',0
nx2:
pop ax
call print
dec bx
jnz drl
call jcrlf
db 13,10,0
jcrlf:
pop ax
call print
pop ds
add sp,3*4 + 6*4
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax ;spoiled
pop ebp 
ret

;Convert byte in AL to ascii in AX
;al-->ax=ASCII
h2a:
rol eax,16
xor ax,ax
rol eax,16
mov ah,0
shl ax,4
shr al,4
cmp al,9
jbe hs1
add al,7
hs1:
add al,30h
;
cmp ah,9
jbe hs2
add ah,7
hs2:
add ah,30h
;
xchg al,ah
ret

;###################### MBR/LDR floppy staff
;ax=sz_loader in sct; check size of loader, it must be < (nsct - 1)
;CF on error;
disk_info:
pushad
push ax
mov ah,8
mov dl,DISK_FLOPPY
call int13
;CHS
mov eax,ecx
xchg al,ah
shr ah,6  ;cx=cyl
shr dx,8 ;dx=nhdr
mov [ncyl],ax
mov [nhdr],dx
and cx,111111b
mov [nsct],cx
pop ax
dec cx
cmp ax,cx
ja .ja
clc
popad
ret
.ja:
stc
popad
ret
nsct dw 0
ncyl dw 0
nhdr dw 0


;es:ax = buf,ebx=chs,ecx=nbytes,dx=disk, ds:si=off sect after last read
read_disk:
pushad
mov ebp,ecx
test ebp,SECT_SZ - 1
je kr1r
add ebp,SECT_SZ
kr1r:
shr ebp,SECT_SHIFT
mov edi,ebx
mov bx,ax
wdlr:
mov cx,READ_TRYES
.go:
push cx
call disk_reset
mov cx,di
rol edi,16
mov ax,di
mov dh,al
rol edi,16
;
mov ah,02h
mov al,1
call int13
pop cx
jnc jnc0
dec cx
jnz .go
popad
ret
jnc0:
;call payload
mov eax,1
push ebx
mov ebx,edi
call chs_add
mov edi,eax
test si,si
jz .jz
mov dword [ds:si],edi
.jz:
pop ebx
dec ebp
jnz wdlr
popad
clc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;spoil ebp,ecx,edx,
;eax=chs1,ebx=chs2;-->eax=(chs)(eax+ebx)
chs_add:
push ebx
push ebp
push edx
push 0 ;cary
mov cx,ax
and cx,111111b
mov dx,bx
and dx,111111b
add cx,dx
cmp cx,[nsct] ;cx=sct sum
jbe jbe1
inc word [esp]
mov cx,1
jbe1:
mov ebp,ecx; sect
;
mov cx,ax
xchg cl,ch
shr ch,6  ;cx=cyl1
;
mov dx,bx
xchg dl,dh
shr dh,6  ;dx=cyl2
add cx,dx
add cx,word [esp]
mov word [esp],0
cmp cx,[ncyl] ;cx=cyl sum
jbe jbe2
inc word [esp]
xor cx,cx
jbe2:
xchg cl,ch
shl cl,6  ;dx=cyl2
add ebp,ecx; cyl
;
rol eax,16
rol ebx,16
mov ah,0
mov bh,0
add ax,bx
add ax,word [esp]
or ah,ah
jne addchs_err
rol ebp,16
mov bp,ax
rol ebp,16
pop ax
mov eax,ebp
pop edx
pop ebp
pop ebx
ret
addchs_err:
call _msg2
db 'CHS overflow',0
_msg2:
pop ax
call print
jmp abort
ret
;;;;;;;;;;;;;;;;;;;;;;
abort:
cli
hlt
jmp $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

int13:
push es
test cl,111111b
jne i13
or cl,1
i13:
int 13h
pop es
ret
;;;;;;;;;;;;;;;;;;;
;eax=chs-->eax=lba
chs2lba:
push ebx
push ecx
push edx
xor ecx,ecx
mov ebx,eax
rol eax,16
mov ah,0
mov cx,[ncyl]
mul cx
rol eax,16
mov ax,dx
rol eax,16 
mov cx,bx
xchg cl,ch
shr ch,6  ;cx=cyl
add eax,ecx ;eax=cyl
xor ecx,ecx
mov cx,[nsct]
xor edx,edx
mul ecx
test edx,edx
je jecl
call abort
jecl:
and ebx,111111b
add eax,ebx ;eax=sct
dec eax; off
pop edx
pop ecx
pop ebx
ret

;=print with CRLF
pr:
pusha
call print
call pr0
db 13,10,0
pr0:
pop ax
call print
popa
ret

msg:
pushad
mov ah,9
int 21h
popad
ret

;ebx=chs,ax=off (dw s,c,h)
;;;;;;;;;;;;;;;;;;;
chs_unpack:
pushad
mov ax,esct
mov edx,ebx
mov di,ax
mov ax,dx
and ax,111111b
stosw
xchg dl,dh
shr dh,6  ;dx=cyl
mov ax,dx
stosw
shr edx,16
mov ax,dx
mov ah,0
stosw 
popad
ret
esct dw 0
ecyl dw 0
ehdr dw 0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ax-->eax
bytes2chs:
push ecx
push edx
test ax,SECT_SZ - 1
je kr
add ax,SECT_SZ
kr:
shr ax,SECT_SHIFT
mov cx,[nsct]
xor dx,dx
div cx
;ax=cyl,dx=sect,
push dx ;sct
mov cx,[ncyl]
xor dx,dx
div cx
;
;ax =hdr
;dx =cyl
or ah,ah
je b2c
call abort
ret
b2c:
shl eax,16
mov ax,dx
xchg al,ah
shl al,6
pop cx
add ax,cx ;eax=chs packed
pop edx
pop ecx
ret

;;;;;;;;;;;;;;;;;;
MYNAME db '[RM loader]',0
debug:
pushad
push ax

call debug0
db 'Debug: ',0
debug0:
pop ax
call print

mov ax,MYNAME
call print

call debug1
db ': ',0
debug1:
pop ax
call print

pop ax
call print
call pr_crlf
popad
ret
CRLF db 13,10,0


;;;;;
stderr:
push ax
call serr1
db 'Error: ',0
serr1:
pop ax
call print
pop ax
call print
ret

;ds:ax=off->ax = byte after 0x0
;;;
print:
push si
mov si,ax
mov ah,0eh
prbk:
lodsb
or al,al
je prex
int 10h
jmp prbk
prex:
mov ax,si
pop si
ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ds:ax = buf,ebx=chs,ecx=nbytes,dx=disk, si=buf of chs intervals
write_disk:
pushad
test si,si
je .je1
mov di,MAX_CHSINTS_SZ/4
push si
.jnz:
mov dword [si],0
add si,4
dec di
jnz .jnz
pop si
.je1:
mov ebp,ecx
test ebp,SECT_SZ - 1
je kr1w
add ebp,SECT_SZ
kr1w:
shr ebp,SECT_SHIFT
mov edi,ebx
mov bx,ax
push si
push eax ;reserve space for old chs
wdlw:
mov ax,si
sub ax,word [esp+4]
cmp ax,MAX_CHSINTS_SZ - 3*4 ;fail + END
ja near .ex
mov cx,di
rol edi,16
mov ax,di
mov dh,al
rol edi,16
;
mov ah,03h
mov al,1
call disk_reset
call int13
jnc .j1
;fail
test si,si
je near .ex
cmp dword [si],0
je .no
cmp dword [si],-1
je .no
;add si,4
pop eax
push eax
cmp eax,dword [si]
je .je2 ;interval len=1
add si,4
mov dword [si],eax
.je2:
add si,4
mov dword [si],-1
jmp .no
.j1: ;ok
mov dword [esp],edi ;update old
test si,si
jz .no
cmp dword [si],0
jne .jne
mov dword [si],edi
jmp .no
.jne:
cmp dword [si],-1 ;end of interval
jne .no
add si,4
mov dword [si],edi
.no:
mov eax,1
push ebx
mov ebx,edi
call chs_add
mov edi,eax
pop ebx
add bx,SECT_SZ
dec ebp
jnz wdlw
pop edi
pop ax
cmp dword [si],-1
je .j2
cmp dword [si],0
je .j2
cmp dword [si],edi
je .j2
mov dword [si + 4],edi
.j2:
popad
clc
ret
.ex:
stc
pop edi
pop ax
popad
ret

;;;reset disk
disk_reset:
pushad
xor dx,dx
xor ax,ax
int 13h
popad
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ax,off ptrable, ebx=start CHS, ecx=size in bytes
init_ptable:
pushad
push ecx
mov di,ax
mov al,80h
stosb ;Active
mov eax,ebx
rol eax,16
stosb ;H
rol eax,16
stosw ;CS
mov al,PART_TYPE
stosb
mov ax,cx
;new
cmp ax,SECT_SZ
ja jip
mov eax,ebx
jmp jipnx
jip:
sub ax,SECT_SZ
;end
call bytes2chs
call chs_add
jipnx:
rol eax,16
stosb ;H
rol eax,16
stosw ;CS
mov eax,ebx
call chs2lba
stosd
pop ecx
test ecx,SECT_SZ - 1
je kr1a
add ecx,SECT_SZ
kr1a:
shr ecx,SECT_SHIFT
mov eax,ecx
stosd
popad
ret



;edx
PrintCpuInfo:
pushad
mov eax,edx
mov ebx,edx
mov ecx,edx
mov esi,edx
mov edi,edx

and eax,1111b ;stepping

shr ebx,4
and ebx,1111b ;model

shr ecx,8
and ecx,1111b ;family

shr edx,12
and edx,11b   ;type

shr esi,16
and esi,1111b ;ext.model

shr edi,16 + 4
and edi,1111b ;ext.family

mov bp,sp
p edi
p esi
p edx
p ecx
p ebx
p eax
mov bx,6
mov si,bp
dec si; hi byte
call pci0
db 'Ext.family:',0,'Ext.model:',0,'Type:',0
db 13,10,'Family:',0,'Model=',0,'Stepping=',0
pci0:
pop di
drl2a:
mov ax,di
call print
mov di,ax
mov cx,4
drl2b:
std
xor eax,eax
lodsb
cld
call h2a
push eax
mov ax,sp
call print
pop eax
loop drl2b
call pr_space
dec bx
jnz drl2a
add sp,6*4
popad
ret
